package marmalius;
public class NPC {
    private client v;
    public int npcId;
    public int npcType;
    public boolean IsInCombat = false;
    public boolean attackable = true;
    public int PoisonDelay = 999999;
    public int PoisonClear = 0;
    public int absX, absY;
    public int heightLevel;
    public int makeX, makeY, moverangeX1, moverangeY1, moverangeX2, moverangeY2, moverangeX3, moverangeY3, moveX, moveY, direction, directionz, walkingType, attacknpc, followPlayer;
    public int spawnX, spawnY;
    public int viewX, viewY;
    public int HP, MaxHP, hitDiff, MaxHit, animNumber, actionTimer, StartKilling, enemyX, enemyY;
    public boolean IsDead, DeadApply, NeedRespawn, IsUnderAttack, IsClose, Respawns, IsUnderAttackNpc, IsAttackingNPC, poisondmg, walkingToPlayer, followingPlayer;
    public int[] Killing = new int[PlayerHandler.getInstance().getMaxPlayers()];
    public String followName = "";
    public boolean RandomWalk;
    public boolean dirUpdateRequired;
    public boolean FocusUpdateRequired;
    public boolean animUpdateRequired;
    public boolean hitUpdateRequired;
    public boolean updateRequired;
    public boolean textUpdateRequired;
    public boolean faceToUpdateRequired;
    public String textUpdate;
    public int freezeTimer, poisonTimer, poisonDelay, reducedAttack;
    public boolean poisonDmg;
    public boolean hit = false;
    public int FocusPointX = -1, FocusPointY = -1;
    public int HitTimer = 0;
    public int Frozentimer = 0;
    public boolean isatvoid = false;
    public boolean roundone = true;
    public boolean atvoid = false;	
    public int portal1 = 0;
    public int portal2 = 0;
    public int portal3 = 0;
    public int portal4 = 0;
    public int pcwalktimer = 0;
    public void gfx110(int gfx) {
        v.mask100var1 = gfx;
        v.mask100var2 = 6553600;
        v.mask100update = true;
        v.updateRequired = true;
    }

    public void TurnNPCTo(int pointX, int pointY) {
        FocusPointX = 2 * pointX + 1;
        FocusPointY = 2 * pointY + 1;
    }

    private void appendSetFocusDestination(stream str) {
        str.writeWordBigEndian(FocusPointX);
        str.writeWordBigEndian(FocusPointY);
    }

    public NPC(int _npcId, int _npcType) {
        npcId = _npcId;
        npcType = _npcType;
        direction = -1;
        IsDead = false;
        DeadApply = false;
        actionTimer = 0;
        RandomWalk = true;
        StartKilling = 0;
        IsUnderAttack = false;
        IsClose = false;
        for (int i = 0; i < Killing.length; i++) {
            Killing[i] = 0;
        }
    }
	
    public void updateNPCMovement(stream str) {
        if (direction == -1) {
            // don't have to update the npc position, because the npc is just standing
            if (updateRequired) {
                // tell client there's an update block appended at the end
                str.writeBits(1, 1);
                str.writeBits(2, 0);
            } else {
                str.writeBits(1, 0);
            }
        } else {
            // send "walking packet"
            str.writeBits(1, 1);
            str.writeBits(2, 1); // updateType
            str.writeBits(3, misc.xlateDirectionToClient[direction]);
            if (updateRequired) {
                str.writeBits(1, 1); // tell client there's an update block appended at the end
            } else {
                str.writeBits(1, 0);
            }
        }
    }

    public void appendNPCUpdateBlock(stream str) {
        if (!updateRequired) {
            return;
        }		// nothing required
        int updateMask = 0;

        if (animUpdateRequired) {
            updateMask |= 0x10;
        }
        if (textUpdateRequired) {
            updateMask |= 1;
        }
        if (hitUpdateRequired) {
            updateMask |= 0x40;
        }
        if (FocusUpdateRequired) {
            updateMask |= 0x4;
        } // 4
        if (dirUpdateRequired) {
            updateMask |= 0x80;
        }
        if (faceToUpdateRequired) {
            updateMask |= 0x20;
        }

        /* if(updateMask >= 0x100) {
         // byte isn't sufficient
         updateMask |= 0x40;			// indication for the client that updateMask is stored in a word
         str.writeByte(updateMask & 0xFF);
         str.writeByte(updateMask >> 8);
         } else {*/
        str.writeByte(updateMask);
        // }

        // now writing the various update blocks itself - note that their order crucial
        if (textUpdateRequired) {
            str.writeString(textUpdate);
        }
        if (animUpdateRequired) {
            appendAnimUpdate(str);
        }
        if (hitUpdateRequired) {
            appendHitUpdate(str);
        }
        if (FocusUpdateRequired) {
            appendSetFocusDestination(str);
        }
        if (dirUpdateRequired) {
            appendFaceEntity(str);
        }
        if (faceToUpdateRequired) {
            appendFaceToUpdate(str);
        }
        // TODO: add the various other update blocks
    }

    public boolean ResetAttackPlayer() {
        IsUnderAttack = false;
        StartKilling = 0;
        RandomWalk = true;
        animNumber = 0x328;
        animUpdateRequired = true;
        updateRequired = true;
        return true;
    }

    public void clearUpdateFlags() {
        updateRequired = false;
        textUpdateRequired = false;
        hitUpdateRequired = false;
        FocusUpdateRequired = false;
        animUpdateRequired = false;
        dirUpdateRequired = false;
        textUpdate = null;
        moveX = 0;
        moveY = 0;
        direction = -1;
    }

    // returns 0-7 for next walking direction or -1, if we're not moving
    public int getNextWalkingDirection() {
        int dir;

        dir = misc.direction(absX, absY, (absX + moveX), (absY + moveY));
        if (dir == -1) {
            return -1;
        }
        dir >>= 1;
        absX += moveX;
        absY += moveY;
        return dir;
    }

    public void getNextNPCMovement() {
        direction = -1;
        direction = getNextWalkingDirection();
    }
	
    protected void appendHitUpdate(stream str) {		
        try {
            if (hit == true) {
                HP -= hitDiff;
                hit = false;
            }
            if (HP <= 0) {
                IsDead = true;
            }
            str.writeByteC(hitDiff); // What the npc got 'hit' for
            if (hitDiff > 0 && !poisonDmg) {
                str.writeByteS(1); // 0: red hitting - 1: blue hitting
            } else if (hitDiff > 0 && poisonDmg) {
                str.writeByteS(2); // 0: red hitting - 1: blue hitting
            } else {
                str.writeByteS(0); // 0: red hitting - 1: blue hitting
            }
            str.writeByteS(HP); // Their current hp, for HP bar
            str.writeByteC(MaxHP); // Their max hp, for HP bar
            poisonDmg = false;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void appendHitUpdate2(stream str) {		
        try {
            HP -= hitDiff;
            if (HP <= 0) {
                IsDead = true;
            }
            str.writeByteS(hitDiff); // What the perseon got 'hit' for
            if (hitDiff > 0 && !poisondmg) {
                str.writeByteC(1); // 0: red hitting - 1: blue hitting
            } else if (hitDiff > 0 && poisondmg) {
                str.writeByteC(2); // 0: red hitting - 1: blue hitting
            } else {
                str.writeByteC(0); // 0: red hitting - 1: blue hitting
            }
            str.writeByteS(HP); // Their current hp, for HP bar
            str.writeByte(MaxHP); // Their max hp, for HP bar
            poisondmg = false;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void appendAnimUpdate(stream str) {
        str.writeWordBigEndian(animNumber);
        str.writeByte(1);
    }

    public void appendFaceEntity(stream str) {
        str.writeWord(direction);
    }
        
    public void appendFaceToUpdate(stream str) {
        str.writeWordBigEndian(viewX);
        str.writeWordBigEndian(viewY);
    }
}
